
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.ObjectModel;
using System.Windows.Input;
using Microsoft.Win32;
using System.IO;
using System.Windows;
using Xceed.Wpf.AvalonDock.Layout;
using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using PPP.View;
using PPP.Services;
using PPP.Model;
using PPP.ViewModel.BaseModel;
using PPP.ViewModel.WindowModel;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Printing;
using Xceed.Wpf.AvalonDock;
using NLog;
using PPP.Utils;
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.WindowsAPICodePack.Shell;

namespace PPP.ViewModel {
    /// <summary>
    /// Main ViewModel. 
    /// 
    /// <list type="bullet">
    /// <item>
    /// <term>Author</term>
    /// <description>Sebastian Will</description>
    /// </item>
    /// </list>
    /// 
    /// </summary>    
    public class MainViewModel : ViewModelBase {

        #region Fields

        /// <summary>
        /// The logger.
        /// </summary>
        private readonly Logger _logger = LogManager.GetLogger("MainViewModel");   

        /// <summary>
        /// The main window.
        /// </summary>
        private MainWindow _mainWindow = null;

        /// <summary>
        /// The collection of pictures.
        /// </summary>
        private ObservableCollection<PicturePropertiesViewModel> _pictures = null;

        /// <summary>
        /// The collection of galleries.
        /// </summary>
        private ObservableCollection<GalleryViewModel> _galleries = null;

        /// <summary>
        /// The PropertiesViewModel.
        /// </summary>
        private PropertiesViewModel _propertiesViewModel = null;

        /// <summary>
        /// The PreviewViewModel.
        /// </summary>
        private PreviewViewModel _previewViewModel = null;

        /// <summary>
        /// The USBViewModel.
        /// </summary>
        private USBViewModel _usbViewModel = null;
        
        /// <summary>
        /// The RibbonViewModel.
        /// </summary>
        private RibbonViewModel _ribbonViewModel = null;

        /// <summary>
        /// The PrintViewModel.
        /// </summary>
        private PrintViewModel _printViewModel = null;

        /// <summary>
        /// Array of all Toolboxes.
        /// </summary>
        ToolViewModel[] _tools = null;

        /// <summary>
        /// The selected GalleryViewModel.
        /// </summary>
        private GalleryViewModel _selectedGallery = null;

        //RelayCommand<object> _openCommand = null;
        RelayCommand<object> _exitCommand = null;
        RelayCommand<object> _printCommand = null;
        RelayCommand<object> _helpCommand = null;
        RelayCommand<object> _selectRibbonTabItemCommand = null;
        RelayCommand<object> _usbConnectorOpenGalleryCommand = null;

        RelayCommand<object> _selectSortCriteriaCommand = null;
        RelayCommand<object> _gallerySortAZCommand = null;
        RelayCommand<object> _gallerySortZACommand = null;

        RelayCommand<object> _homeOpenGalleryCommand = null;        

        /// <summary>
        /// Sort criteria to sort pictures in a gallery. 
        /// </summary>
        private PPP.Misc.Enums.Enums.SortCriteria _sortCriteria =  Misc.Enums.Enums.SortCriteria.CreationDate;
               
        private IPicturesService _picturesService;

        #endregion

        #region PropertyName Consts
        
        #endregion

        #region Properties

        /// <summary>
        /// Gets the main window property.        
        /// </summary>
        public MainWindow MainWindow {
            get {
                if (_mainWindow == null) {
                    _propertiesViewModel = new PropertiesViewModel();
                    _usbViewModel = new USBViewModel();
                }

                return _mainWindow;
            }
        }

        /// <summary>
        /// Gets the PropertiesViewModel property.        
        /// </summary>
        public PropertiesViewModel PropertiesViewModel {
            get {
                if (_propertiesViewModel == null)
                    _propertiesViewModel = new PropertiesViewModel();

                return _propertiesViewModel;
            }
        }

        /// <summary>
        /// Gets the PreviewViewModel property.        
        /// </summary>
        public PreviewViewModel PreviewViewModel {
            get {
                if (_previewViewModel == null)
                    _previewViewModel = new PreviewViewModel();

                return _previewViewModel;
            }
        }

        /// <summary>
        /// Gets the USBViewModel property.        
        /// </summary>
        public USBViewModel USBViewModel {
            get {
                if (_usbViewModel == null)
                    _usbViewModel = new USBViewModel();

                return _usbViewModel;
            }

            set {
                _usbViewModel = value;
            }
        }

        /// <summary>
        /// Gets the RibbonViewModel property.        
        /// </summary>
        public RibbonViewModel RibbonViewModel {
            get {
                if (_ribbonViewModel == null)
                    _ribbonViewModel = new RibbonViewModel();

                return _ribbonViewModel;
            }
        }

        /// <summary>
        /// Gets the PrintViewModel property.        
        /// </summary>
        public PrintViewModel PrintViewModel {
            get {
                if (_printViewModel == null)
                    _printViewModel = new PrintViewModel();

                return _printViewModel;
            }
        }

        /// <summary>
        /// Gets the Pictures property.        
        /// </summary>
        public ObservableCollection<PicturePropertiesViewModel> Pictures {
            get {
                if (_pictures == null)
                    _pictures = new ObservableCollection<PicturePropertiesViewModel>();

                return _pictures;
            }

            set { _pictures = value; }
        }

        /// <summary>
        /// Gets the Galleries property.        
        /// </summary>
        public ObservableCollection<GalleryViewModel> Galleries {
            get {
                if (_galleries == null)
                    _galleries = new ObservableCollection<GalleryViewModel>();

                return _galleries;
            }
        }

        /// <summary>
        /// Gets the Tools property.        
        /// </summary>
        public IEnumerable<ToolViewModel> Tools {
            get {
                if (_tools == null)
                    _tools = new ToolViewModel[] { PropertiesViewModel, PreviewViewModel, USBViewModel};
                return _tools;
            }
        }

        /// <summary>
        /// Gets the selected gallery property.
        /// </summary>
        public GalleryViewModel SelectedGallery {
            get {                
                return _selectedGallery;
            }
            set { _selectedGallery = value; }
        }

        #region Commands

        //public RelayCommand LoadPicturesCommand {
        //    get;
        //    private set;
        //}

        public ICommand ExitCommand {
            get {
                if (_exitCommand == null) {
                    _exitCommand = new RelayCommand<object>((p) => OnExit(p), (p) => CanExit(p));
                }
                return _exitCommand;
            }
        }

        public ICommand HelpCommand {
            get {
                if (_helpCommand == null) {
                    _helpCommand = new RelayCommand<object>((p) => OnHelp(p), (p) => CanHelp(p));
                }
                return _helpCommand;
            }
        }

        public ICommand PrintCommand {
            get {
                if (_printCommand == null) {
                    _printCommand = new RelayCommand<object>((p) => OnPrint(p), (p) => CanPrint(p));
                }
                return _printCommand;
            }
        }

        public ICommand SelectRibbonTabItemCommand {
            get {
                if (_selectRibbonTabItemCommand == null) {
                    _selectRibbonTabItemCommand = new RelayCommand<object>((p) => OnSelectRibbonTabItem(p));
                }
                return _selectRibbonTabItemCommand;
            }
        }

        public ICommand USBConnectorOpenGalleryCommand {
            get {
                if ( _usbConnectorOpenGalleryCommand == null) {
                    _usbConnectorOpenGalleryCommand = new RelayCommand<object>((p) => OnUSBConnectorOpenGallery(p), (p) => CanUSBConnectorOpenGallery(p));
                }
                return _usbConnectorOpenGalleryCommand;
            }
        }

        public ICommand SelectSortCriteriaCommand {
            get {
                if (_selectSortCriteriaCommand == null) {
                    _selectSortCriteriaCommand = new RelayCommand<object>((p) => OnSelectSortCriteria(p));
                }
                return _selectSortCriteriaCommand;
            }
        }

        public ICommand GallerySortAZCommand {
            get {
                if ( _gallerySortAZCommand == null) {
                    _gallerySortAZCommand = new RelayCommand<object>((p) => OnGallerySortAZ(p), (p) => CanGallerySortAZ(p));
                }
                return _gallerySortAZCommand;
            }
        }

        public ICommand GallerySortZACommand {
            get {
                if (_gallerySortZACommand == null) {
                    _gallerySortZACommand = new RelayCommand<object>((p) => OnGallerySortZA(p), (p) => CanGallerySortZA(p));
                }
                return _gallerySortZACommand;
            }
        }

        public ICommand HomeOpenGalleryCommand {
            get {
                if ( _homeOpenGalleryCommand == null) {
                    _homeOpenGalleryCommand = new RelayCommand<object>((p) => OnHomeOpenGallery(p), (p) => CanHomeOpenGallery(p));
                }
                return _homeOpenGalleryCommand;
            }
        }
        
        

        #endregion                        
        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the MainViewModel class.
        /// </summary>
        public MainViewModel(MainWindow mainWindow, IPicturesService picturesService) {

            _mainWindow = mainWindow;
            _picturesService = picturesService;

            //Pictures = new ObservableCollection<PictureViewModel>();

            //LoadPicturesCommand = new RelayCommand(
            //    () => {
            //        //IsBusy = true;
            //        _picturesService.GetPictures(GetPicturesCompleted);
            //    });

            _picturesService.GetPictures(GetPicturesCompleted);

            GalleryViewModel gelleryViewModel = new GalleryViewModel(Pictures);
            SelectedGallery = gelleryViewModel;
            Galleries.Add(gelleryViewModel);        

            if (IsInDesignMode) {
                _picturesService.GetPictures(GetPicturesCompleted);
            }
        }
       
        #endregion

        #region Methods

        private void GetPicturesCompleted(IList<Picture> result, Exception error) {
            if (error != null) {
                MessageBox.Show(error.Message);
                //IsBusy = false;
                return;
            }

            if (result == null) {
                MessageBox.Show("Nothing found");
                //IsBusy = false;
                return;
            }

            Pictures.Clear();
            foreach (var picture in result) {
                Pictures.Add(new PicturePropertiesViewModel(picture));
            }

            //IsBusy = false;
        }

        /// <summary>
        /// Is exiting allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanExit(object parameter) {
            return true;
        }

        /// <summary>
        /// Is printing allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanPrint(object parameter) {
            return true;
        }

        /// <summary>
        /// Is open help allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanHelp(object parameter) {
            return true;
        }

        /// <summary>
        /// Is open usb connector gallery allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanUSBConnectorOpenGallery(object parameter) {
            return USBViewModel.SelectedUSBDevice != null ? true : false;
        }        
        
        /// <summary>
        /// Is sort az gallery allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanGallerySortAZ(object parameter) {
            return (Galleries.Count > 0 && Galleries[0].Pictures.Count > 0) ? true : false;
        }

        /// <summary>
        /// Is sort za gallery allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanGallerySortZA(object parameter) {
            return (Galleries.Count > 0 && Galleries[0].Pictures.Count > 0) ? true : false;
        }

        /// <summary>
        /// Is open gallery allowed.
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        private bool CanHomeOpenGallery(object parameter) {
            return true;
        }
        


        /// <summary>
        /// Exit the application.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnExit(object parameter) {
            MainWindow.Close();
        }

        /// <summary>
        /// Open the help screen. What the fucking help screen? This is low budget production. 
        /// </summary>
        /// <param name="parameter"></param>
        private void OnHelp(object parameter) {
            
        }

        /// <summary>
        /// Select the sort creteria.
        /// </summary>
        /// <param name="parameter">The sort criteria.</param>
        /// <returns></returns>
        private bool OnSelectSortCriteria(object parameter) {
            try {
                _sortCriteria = (PPP.Misc.Enums.Enums.SortCriteria)Enum.Parse(typeof(PPP.Misc.Enums.Enums.SortCriteria), parameter.ToString());
                return true;
            }
            catch (Exception ex) {
                _logger.ErrorException("Can't cast string to sort criteria.", ex);
                return false;
            }
        }

        /// <summary>
        /// Open/Load the pictures from the selected usb device.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnUSBConnectorOpenGallery(object parameter) {

            string  usbDevice = USBViewModel.SelectedUSBDevice.USBDevice.Name;
            if (!string.IsNullOrWhiteSpace(usbDevice)) {
                _logger.Info(string.Format("Load Pictures from usb device: {0}", usbDevice));
                _picturesService = new HardDrivePicturesService(@usbDevice,true);
                _picturesService.GetPictures(GetPicturesCompleted);
            }
            else {
                _logger.Info("Cant' load pictures from usb device. No usb device selected.");
            }
        }

        

        
        /// <summary>
        /// Sort az the gallery.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnGallerySortAZ(object parameter) {

            switch (_sortCriteria) {
                case PPP.Misc.Enums.Enums.SortCriteria.Name:
                    DataUtils.Sort<PicturePropertiesViewModel, string>(Galleries[0].Pictures, a => a.Picture.FileInfo.Name, null, System.ComponentModel.ListSortDirection.Ascending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.CreationDate:
                    DataUtils.Sort<PicturePropertiesViewModel, DateTime>(Galleries[0].Pictures, a => a.Picture.FileInfo.CreationTime, null, System.ComponentModel.ListSortDirection.Ascending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.ModificationDate:
                    DataUtils.Sort<PicturePropertiesViewModel, DateTime>(Galleries[0].Pictures, a => a.Picture.FileInfo.LastWriteTime, null, System.ComponentModel.ListSortDirection.Ascending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.Size:
                    DataUtils.Sort<PicturePropertiesViewModel, long>(Galleries[0].Pictures, a => a.Picture.FileInfo.Length, null, System.ComponentModel.ListSortDirection.Ascending);
                    break;
                default:
                    break;
            }

            
        }

        /// <summary>
        /// Sort za the gallery.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnGallerySortZA(object parameter) {

            switch (_sortCriteria) {
                case PPP.Misc.Enums.Enums.SortCriteria.Name:
                    DataUtils.Sort<PicturePropertiesViewModel, string>(Galleries[0].Pictures, a => a.Picture.FileInfo.Name, null, System.ComponentModel.ListSortDirection.Descending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.CreationDate:
                    DataUtils.Sort<PicturePropertiesViewModel, DateTime>(Galleries[0].Pictures, a => a.Picture.FileInfo.CreationTime, null, System.ComponentModel.ListSortDirection.Descending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.ModificationDate:
                    DataUtils.Sort<PicturePropertiesViewModel, DateTime>(Galleries[0].Pictures, a => a.Picture.FileInfo.LastWriteTime, null, System.ComponentModel.ListSortDirection.Descending);
                    break;
                case PPP.Misc.Enums.Enums.SortCriteria.Size:
                    DataUtils.Sort<PicturePropertiesViewModel, long>(Galleries[0].Pictures, a => a.Picture.FileInfo.Length, null, System.ComponentModel.ListSortDirection.Descending);
                    break;
                default:
                    break;
            }
            
        }

        /// <summary>
        /// Select the ribbon tab item.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnSelectRibbonTabItem(object parameter) {

            List<object> parameters = (List<object>)(parameter);

            DockingManager dockingManager = ((DockingManager)parameters[0]);
            Fluent.Ribbon ribbon = ((Fluent.Ribbon)parameters[1]);
            Type activeContentType = null;            
            if (dockingManager != null && dockingManager.ActiveContent != null && ribbon != null) {
                activeContentType = dockingManager.ActiveContent.GetType();

                switch (activeContentType.Name) {
                    case "PropertiesViewModel":
                        ribbon.SelectedTabIndex = ribbon.Tabs.IndexOf(ribbon.Tabs.Where(x => x.Name.Equals("homeTabItem")).FirstOrDefault());
                        break;
                    case "PreviewViewModel":
                        ribbon.SelectedTabIndex = ribbon.Tabs.IndexOf(ribbon.Tabs.Where(x => x.Name.Equals("homeTabItem")).FirstOrDefault());
                        break;
                    case "GalleryViewModel":
                        ribbon.SelectedTabIndex = ribbon.Tabs.IndexOf(ribbon.Tabs.Where(x => x.Name.Equals("homeTabItem")).FirstOrDefault());
                        break;
                    case "USBViewModel":
                        ribbon.SelectedTabIndex = ribbon.Tabs.IndexOf(ribbon.Tabs.Where(x => x.Name.Equals("usbConnectorTabItem")).FirstOrDefault());                        
                        break;
                    default:
                        ribbon.SelectedTabIndex = ribbon.Tabs.IndexOf(ribbon.Tabs.Where(x => x.Name.Equals("homeTabItem")).FirstOrDefault());
                        break;
                }
            }
            
        }

        /// <summary>
        /// Open/Load the pictures from the selected folder.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnHomeOpenGallery(object parameter) {

            string directory = string.Empty;

            CommonOpenFileDialog OpenFileDialog = new CommonOpenFileDialog();
            OpenFileDialog.IsFolderPicker = true;
            OpenFileDialog.InitialDirectory = KnownFolders.Desktop.Path; 
            
            
            if (OpenFileDialog.ShowDialog() == CommonFileDialogResult.Ok) {
                directory = OpenFileDialog.FileName;
                if (!string.IsNullOrWhiteSpace(directory)) {
                    _logger.Info(string.Format("Load pictures from folder: {0}", directory));
                    _picturesService = new HardDrivePicturesService(@directory, true);
                    _picturesService.GetPictures(GetPicturesCompleted);
                }
            }
            else {
                _logger.Info("Load pictures from folder canceled.");
            }
        }
        
        

        /// <summary>
        /// Print the previewed picture.
        /// </summary>
        /// <param name="parameter"></param>
        private void OnPrint(object parameter) {

            if (_previewViewModel.SelectedPicture != null) {
                
                var bi = new BitmapImage();
                bi.BeginInit();
                bi.CacheOption = BitmapCacheOption.OnLoad;
                bi.UriSource = _previewViewModel.SelectedPicture.Picture.PictureUri;
                bi.EndInit();

                var printDialog = new PrintDialog();
                printDialog.PrintTicket.PageOrientation = PageOrientation.Landscape;
                printDialog.PrintTicket.PageBorderless = PageBorderless.Borderless;
                System.Printing.PrintCapabilities capabilities = printDialog.PrintQueue.GetPrintCapabilities(printDialog.PrintTicket);

                var visual = new DrawingVisual();
                var drawContext = visual.RenderOpen();
                drawContext.DrawImage(bi, new Rect { Width = capabilities.PageImageableArea.ExtentWidth, Height = capabilities.PageImageableArea.ExtentHeight });
                drawContext.Close();

                
                if (printDialog.ShowDialog() == true) {
                    
                    printDialog.PrintVisual(visual, _previewViewModel.SelectedPicture.Picture.PictureUri.LocalPath);
                }

                


            }
        }

        #endregion

                
        

        //#region OpenCommand
        
        //public ICommand OpenCommand {
        //    get {
        //        if (_openCommand == null) {
        //            _openCommand = new RelayCommand<object>((p) => OnOpen(p), (p) => CanOpen(p));
        //        }

        //        return _openCommand;
        //    }
        //}

        //private bool CanOpen(object parameter) {
        //    return true;
        //}

        //private void OnOpen(object parameter) {
        //    var dlg = new OpenFileDialog();
        //    if (dlg.ShowDialog().GetValueOrDefault()) {
        //        var fileViewModel = Open(dlg.FileName);
        //        ActiveDocument = fileViewModel;
        //    }
        //}

        //public FileViewModel Open(string filepath) {
        //    var fileViewModel = _files.FirstOrDefault(fm => fm.FilePath == filepath);
        //    if (fileViewModel != null)
        //        return fileViewModel;

        //    fileViewModel = new FileViewModel(filepath);
        //    _files.Add(fileViewModel);
        //    return fileViewModel;
        //}

        //#endregion

    //    #region NewCommand
    //    RelayCommand<object> _newCommand = null;
    //    public ICommand NewCommand {
    //        get {
    //            if (_newCommand == null) {
    //                _newCommand = new RelayCommand<object>((p) => OnNew(p), (p) => CanNew(p));
    //            }

    //            return _newCommand;
    //        }
    //    }

    //    private bool CanNew(object parameter) {
    //        return true;
    //    }

    //    private void OnNew(object parameter) {
    //        _files.Add(new FileViewModel());
    //        ActiveDocument = _files.Last();
    //    }

    //    #endregion

    //    #region ActiveDocument

    //    private FileViewModel _activeDocument = null;
    //    public FileViewModel ActiveDocument {
    //        get { return _activeDocument; }
    //        set {
    //            if (_activeDocument != value) {
    //                _activeDocument = value;
    //                RaisePropertyChanged("ActiveDocument");
    //                if (ActiveDocumentChanged != null)
    //                    ActiveDocumentChanged(this, EventArgs.Empty);
    //            }
    //        }
    //    }

    //    public event EventHandler ActiveDocumentChanged;

    //    #endregion


    //    internal void Close(FileViewModel fileToClose) {
    //        if (fileToClose.IsDirty) {
    //            var res = MessageBox.Show(string.Format("Save changes for file '{0}'?", fileToClose.FileName), "AvalonDock Test App", MessageBoxButton.YesNoCancel);
    //            if (res == MessageBoxResult.Cancel)
    //                return;
    //            if (res == MessageBoxResult.Yes) {
    //                Save(fileToClose);
    //            }
    //        }

    //        _files.Remove(fileToClose);
    //    }

    //    internal void Save(FileViewModel fileToSave, bool saveAsFlag = false) {
    //        if (fileToSave.FilePath == null || saveAsFlag) {
    //            var dlg = new SaveFileDialog();
    //            if (dlg.ShowDialog().GetValueOrDefault())
    //                fileToSave.FilePath = dlg.SafeFileName;
    //        }

    //        File.WriteAllText(fileToSave.FilePath, fileToSave.TextContent);
    //        ActiveDocument.IsDirty = false;
    //    }
    }    
}
